package com.gitee.huanminabc.fastboot.load.metainfo;

import com.gitee.huanminabc.jcommon.file.IoStreamUtil;
import com.gitee.huanminabc.jcommon.reflect.ClassUtil;
import com.gitee.huanminabc.jcommon.reflect.MetaInfScanner;
import com.gitee.huanminabc.jcommon.str.StringUtil;
import com.gitee.huanminabc.jcommon.test.PathUtil;
import com.gitee.huanminabc.fastboot.context.AppContext;
import com.gitee.huanminabc.fastboot.load.classload.ClassLoadIntercept;
import com.gitee.huanminabc.fastboot.load.hook.*;
import com.gitee.huanminabc.fastboot.load.stage.*;
import com.gitee.huanminabc.fastboot.load.stage.poststage.AppLoadPostStage;
import com.gitee.huanminabc.fastboot.load.stage.prestage.AppLoadPreStage;
import com.gitee.huanminabc.fastboot.load.stage.syncstage.AppLoadSyncStage;
import lombok.extern.slf4j.Slf4j;

import java.io.InputStream;
import java.util.List;

/**
 * 简要描述
 *
 * @Author: huanmin
 * @Date: 2025/4/12 22:42
 * @Version: 1.0
 * @Description: 文件作用详细描述....
 */
@Slf4j
public class ScanMetaInfoFactories {
    public final static String fileName = "fastboot.factories";

    public static void load() {
        try {
            List<InputStream> filesInMetaInf = MetaInfScanner.readFilesInMetaInf(fileName);
            if (filesInMetaInf.isEmpty()) {
                log.debug("没有找到 {} 文件", fileName);
                return;
            }
            for (InputStream inputStream : filesInMetaInf) {
                try {
                    String str = IoStreamUtil.inputStreamToStr(inputStream);
                    //按照行读取
                    String[] lines = str.split("\n");
                    for (String line : lines) {
                        line = line.trim();
                        if (StringUtil.isEmpty(line)){
                            continue;
                        }
                        log.debug(fileName+"加载 {}", line);
                        Class<?> aClass = ClassUtil.loadClass(line);
                        //类拦截器加载
                        if (ClassLoadIntercept.class.isAssignableFrom(aClass)) {
                            AppContext.classLoadIntercepts.add((ClassLoadIntercept) ClassUtil.newInstance(aClass));
                        }
                        //阶段加载
                        boolean stage = stage(aClass);
                        if (stage) {
                            continue;
                        }
                        //钩子加载
                        boolean hook = hook(aClass);
                        if (hook) {
                            continue;
                        }
                    }
                } finally {
                    inputStream.close();
                }
            }

        } catch (Exception e) {
            log.error("ScanMetaInfoFactories load error", e);
            System.exit(1);
        }

    }


    private static boolean stage(Class<?> aClass) {
        if (AppLoadSyncStage.class.isAssignableFrom(aClass)) {
            SyncStageLauncher.appLoadStages.add((AppLoadSyncStage) ClassUtil.newInstance(aClass));
            return true;
        } else if (AppLoadPreStage.class.isAssignableFrom(aClass)) {
            PreStageLauncher.appLoadStages.add((AppLoadPreStage) ClassUtil.newInstance(aClass));
            return true;
        } else if (AppLoadPostStage.class.isAssignableFrom(aClass)) {
            PostStageLauncher.appLoadStages.add((AppLoadPostStage) ClassUtil.newInstance(aClass));
            return true;
        }
        return false;
    }

    private static boolean hook(Class<?> aClass) {
        if (AppLoadFinishHook.class.isAssignableFrom(aClass)) {
            AppLoadFinishLifecycleHook.appLoadFinishHooks.add((AppLoadFinishHook) ClassUtil.newInstance(aClass));
            return true;
        } else if (AppStartHook.class.isAssignableFrom(aClass)) {
            AppStartHookLifecycleHook.appStartHooks.add((AppStartHook) ClassUtil.newInstance(aClass));
            return true;
        } else if (AppStopHook.class.isAssignableFrom(aClass)) {
            AppStopHookLifecycleHook.appStopHooks.add((AppStopHook) ClassUtil.newInstance(aClass));
            return true;
        } else if (ClassLoadContainerFinishHook.class.isAssignableFrom(aClass)) {
            ClassLoadContainerFinishLifecycleHook.classLoadContainerFinishHooks.add((ClassLoadContainerFinishHook) ClassUtil.newInstance(aClass));
            return true;
        } else if (ConfigValueInjectionFinishHook.class.isAssignableFrom(aClass)) {
            ConfigValueInjectionFinishLifecycleHook.configValueInjectionFinishHooks.add((ConfigValueInjectionFinishHook) ClassUtil.newInstance(aClass));
            return true;
        } else if (DependencyInjectionFinishHook.class.isAssignableFrom(aClass)) {
            DependencyInjectionFinishLifecycleHook.dependencyInjectionFinishHooks.add((DependencyInjectionFinishHook) ClassUtil.newInstance(aClass));
            return true;
        } else if (LoadAppConfigFinishHook.class.isAssignableFrom(aClass)) {
            LoadAppConfigFinishLifecycleHook.loadAppConfigFinishHooks.add((LoadAppConfigFinishHook) ClassUtil.newInstance(aClass));
            return true;
        } else if (ProjectClassLoadFinishHook.class.isAssignableFrom(aClass)) {
            ProjectClassLoadFinishLifecycleHook.projectClassLoadFinishHooks.add((ProjectClassLoadFinishHook) ClassUtil.newInstance(aClass));
            return true;
        }
        return false;
    }
}
